﻿using System;
using System.Windows;
using System.ServiceModel;
using System.Windows.Threading;
using StockholmsStad.Utilities.Exceptions;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Windows.UI.Facade;
using StockholmsStad.Utilities.Enums;
using StockholmsStad.Windows.UI.Infrastructure.Interfaces;
using StockholmsStad.Windows.UI.Infrastructure.Services;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;
using System.Diagnostics;

namespace StockholmsStad.Windows.UI
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        private IApplicationService applicationService; 
        private User user;
        private bool Authenticate(string username, string password)
        {
            user = new User {Username = username, Password = password, Role = UserRole.ReadOnly};
            var userFacade = new UserFacade(user);
            user = userFacade.Logon();
            applicationService = new ApplicationService();
            applicationService.SetCurrentUser(user);
            return user != null;
        }

        protected override void OnStartup(StartupEventArgs e)
        {
            Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
            AppDomain.CurrentDomain.UnhandledException += AppDomainUnhandledException;

            StartupContainer();
        }

        private void StartupContainer()
        {
            Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;

            // Var kommer splashen in i bilden???
            //var splash = new ParvisSplashScreen { DataContext = new ParvisSplashModel() };
            //splash.Show();
            //Current.MainWindow = null;

            
            //Logon
            var logon = new LogonScreen();
            bool? logonResult = logon.ShowDialog();

            if (logonResult.HasValue)
            {
                if(logonResult.Value && Authenticate(logon.UserName, logon.Password))
                {
                    var bootStrapper = new Bootstrapper(user);
                    bootStrapper.Run();
                    bootStrapper.ShowView();
                    Current.ShutdownMode = ShutdownMode.OnMainWindowClose;                    
                }
                else if(!logonResult.Value)
                {
                    Current.Shutdown();
                }
                else
                {
                    throw new StockholmStadApplicationException(ApplicationErrorCode.UserNotAuthorized, Severity.Low);
                }
            }
            else
            {
                // Should hopefully never occur
                throw new StockholmStadApplicationException(ApplicationErrorCode.UnknownError, Severity.Low);
            }

            //splash.Close();
        }

        private static void AppDomainUnhandledException(object sender, UnhandledExceptionEventArgs eventArgs)
        {
            HandleException(eventArgs.ExceptionObject as Exception);
        }

        private static void Current_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
            HandleException(e.Exception);
        }

        private static void HandleException(Exception e)
        {
            bool shutdownApplication = false;
            string errorMessage = string.Empty;
            string extendedErrorMessage = String.Empty;

            if (e is FaultException<StockholmStadSystemErrorFault>)
            {
                var errorInfo = (e as FaultException<StockholmStadSystemErrorFault>).Detail;

                errorMessage = ExceptionManager.TranslateErrorCode(errorInfo.ErrorCode);
                ExceptionManager.WriteToEventLog(errorInfo.ErrorMessage, EventLogEntryType.Error);
            }
            else if (e is FaultException<StockholmStadApplicationErrorFault>)
            {
                var errorInfo = (e as FaultException<StockholmStadApplicationErrorFault>).Detail;

                errorMessage = ExceptionManager.TranslateErrorCode(errorInfo.ErrorCode);
                ExceptionManager.WriteToEventLog(errorInfo.ErrorMessage, EventLogEntryType.Error);
                shutdownApplication = true;
            }
            else if (e is StockholmStadSystemException || e is FaultException<StockholmStadSystemException>)
            {
                var errorInfo = e as StockholmStadSystemException;
    
                if(errorInfo != null)
                {
                    errorMessage = ExceptionManager.TranslateErrorCode(errorInfo.ErrorCode);
                    ExceptionManager.WriteToEventLog(errorInfo.Message, EventLogEntryType.Error);                    
                }
                else
                {
                    ExceptionManager.WriteToEventLog(e.Message, EventLogEntryType.Error);                    
                }
            }
            else if (e is FaultException || e is FaultException<ExceptionDetail>)
            {
                errorMessage = "Det gick inte att kommunicera med servern";
                extendedErrorMessage = ExceptionManager.GetDetailedExceptionInformationRecursive(e);
                ExceptionManager.WriteToEventLog(extendedErrorMessage, EventLogEntryType.Error);
            }
            else if(e is CommunicationException)
            {
                errorMessage = "Det gick inte att kommunicera med servern";
                extendedErrorMessage = ExceptionManager.GetDetailedExceptionInformationRecursive(e);
                ExceptionManager.WriteToEventLog(extendedErrorMessage, EventLogEntryType.Error);
                shutdownApplication = true;                
            }
            else if (e is StockholmStadApplicationException)
            {
                var errorInfo = e as StockholmStadApplicationException;

                errorMessage = ExceptionManager.TranslateErrorCode(errorInfo.ErrorCode);
                extendedErrorMessage = ExceptionManager.GetDetailedExceptionInformationRecursive(e);
                ExceptionManager.WriteToEventLog(extendedErrorMessage, EventLogEntryType.Error);
                shutdownApplication = true;
            }
            else
            {
                // Should never occur....
                errorMessage = e.Message;
            }

            if (shutdownApplication)
                errorMessage += " Applikationen kommer nu stängas ned. Prova igen och kontakta administratör om det händer igen.";

            if (extendedErrorMessage == string.Empty)
            {
                MessageBox.Show(errorMessage, "Felmeddelande", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            else
            {
                var errorWindow = new ExceptionWindow
                {
                    Title = "Felmeddelande",
                    MessageText = errorMessage, //+ "\n\n" + e.Message),
                    ExtendedMessageText = extendedErrorMessage,
                    //Owner = Application.Current.MainWindow
                };

                if (errorWindow.Owner != null)
                    errorWindow.Owner = Current.MainWindow;

                errorWindow.ShowDialog();
            }

            // Close down if serious exception
            if (shutdownApplication)
            {
                Current.Shutdown();
            }
        }
    }
}